Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/449.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使图像处理逐像素快速?_Javascript_Performance_Image Processing_Canvas_Webgl - Fatal编程技术网

Javascript 如何使图像处理逐像素快速?

Javascript 如何使图像处理逐像素快速?,javascript,performance,image-processing,canvas,webgl,Javascript,Performance,Image Processing,Canvas,Webgl,使用2D画布上下文,我在中实现了一个图像处理算法 具有以下特征的JavaScript: 每一行都可以单独处理 每行从左到右进行处理。图像中像素的颜色 输出图像通过以下公式计算: 当前位置输入图像中的颜色 对于第一个像素之后的所有像素:中输出图片的颜色 前一个位置,即左侧一个像素 相应地,算法的运行时间为:O(n) Chrome 52中的算法非常慢,因为画布操作非常慢: 读取输入图像中当前位置的颜色: inputImageData.slice(位置,位置+4) (正在读取输出图像中上一位

使用2D画布上下文,我在中实现了一个图像处理算法 具有以下特征的JavaScript:

  • 每一行都可以单独处理

  • 每行从左到右进行处理。图像中像素的颜色 输出图像通过以下公式计算:

    • 当前位置输入图像中的颜色

    • 对于第一个像素之后的所有像素:中输出图片的颜色 前一个位置,即左侧一个像素

相应地,算法的运行时间为:O(n)

Chrome 52中的算法非常慢,因为画布操作非常慢:

  • 读取输入图像中当前位置的颜色:
    inputImageData.slice(位置,位置+4)

  • (正在读取输出图像中上一位置的输出颜色。) 快,它来自一个变量)

  • 将像素写入输出图像,根据Chrome的profiler,这是 占用大部分时间的单个操作:

    outputImageContext.fillStyle = outputColor;
    outputImageContext.fillRect(x, y, 1, 1);
    
我研究了WebGL的图像处理。然而,它似乎不适用 因为使用WebGL,所有像素都是独立计算的。算法
强制从左向右扫描。

我很抱歉没有理解:您说输出应该是左侧一个像素的输入颜色,但您的“读取”算法显示位置+4

但是,如果我明白这应该是做什么,似乎有一个非常优化的方式来做这件事。在我看来,你正在拍摄一幅图像,并将其向右移动一个像素。然后,最左边的空列由前一列像素填充


使用正确的算法,您应该能够使用原始数据,但可以复制第一列,是吗?

不清楚您想要实现什么

根据你的描述

每行从左到右进行处理。输出图像中像素的颜色由以下公式计算:

  • 当前位置输入图像中的颜色
  • 对于第一个像素之后的所有像素:前一位置输出图片的颜色,即左侧的一个像素
听起来像是要在整个图像上涂抹第一列

  • 第1列=第1列
  • 第2列=第1列
  • 第三列=第二列
  • 第四列=第三列
从左向右处理这只是重复的第一列。如果是这样,只需调用
ctx.drawImage(ctx.canvas,0,0,1,ctx.canvas.height,0,0,ctx.canvas.width,ctx.canvas.height)
将画布用作图像,取第一列并展开它以填充整个画布

否则我真的不理解你的算法。对不起

在任何情况下,假设您确实需要立即引用之前像素的结果,然后再做一些事情

切片imagedata.data以提取像素的速度将很慢。每个片都是内存分配。如果你想提高速度,最好不要为每个像素创建一个新对象

至于写入,是的,使用
fillRect
一次设置一个像素会非常慢。直接在
ImageData
中设置像素,然后将ImageData放回画布,怎么样

否则,尽量少做内部循环的工作。如果你只能计算一次,那么就只计算一次

下面是一些混合在一个圆圈中的代码。虽然我认为慢是主观的,但并没有那么慢

var ctx=document.querySelector(“canvas”).getContext(“2d”);
var width=ctx.canvas.width;
变量高度=ctx.canvas.height;
函数r(最小值、最大值){
如果(最大值===未定义){
最大值=最小值;
最小值=0;
}
返回Math.random()*(max-min)+min;
}
函数循环(ctx){
var color=“hsl(“+r(360)+”,“+r(50100)+”%,50%)”;
ctx.beginPath();
ctx.弧(r(宽度),r(高度),r(100),0,数学PI*2,假);
ctx.fillStyle=颜色;
ctx.fill();
}
//把一些图像放到画布上,这样就有一些东西可以处理了
ctx.fillStyle=“白色”;
ctx.fillRect(0,0,宽度,高度);
对于(var ii=0;ii<200;++ii){
牵引圈(ctx);
}
功能流程(时间){
时间*=0.001;
牵引圈(ctx);
//获取图像的副本
var imageData=ctx.getImageData(0,0,宽度,高度);
var像素=imageData.data;
var xoff=数学sin(时间)*15 | 0;
var yoff=数学cos(时间)*15 | 0;
//模糊
对于(变量y=0;y

听起来很理想,您可以完全在服务器端或通过web工作者来完成这项工作。也许你可以拆分这些行,并为每一行创建一个web worker实例,这样你就可以同时运行它们了。@Shilly我想在客户端做这件事,也想看看我能走多远。这不是一个昂贵的算法,只是当前的实现非常缓慢。感谢网络工作者的建议!您是否尝试了w子阵列而不是切片?将需要查看您的算法,以确定是否存在优化的可能性。您打赌为每个像素设置fillstyle+fillrect会很慢!如果你是真的