我的javascript代码用多次混合绘制墙。如果我使用fillRect它更快但不平滑,而且putImageData与它相反,并且需要大约10秒来绘制图像。例如,左边的一个是用fillRect:
创建的
左图中使用的代码;
context_paintLayer.fillStyle = 'rgba(' + pixel.data[0] + ',' + pixel.data[1] + ',' + pixel.data[2] + ',' + pixel.data[3] + ')';
context_paintLayer.fillRect(x, y, 1, 1);
右图中使用的代码;
context_paintLayer.putImageData(pixel, x, y);
如果您愿意,我可以在此发布完整代码。感谢。
function applyPaint(selectedColor)
{
var partitionImageData = context_partitionLayer.getImageData(0, 0, width, height);
var imageData = context_imageLayer.getImageData(0, 0, width, height);
var selectedColorRGB = selectedColor.split("-");
for(var y = targetStartY; y < targetEndY; y++)
{
for(var x = targetStartX; x < targetEndX; x++)
{
var index = ((width * y) + x) * 4;
var r = partitionImageData.data[index];
var g = partitionImageData.data[index + 1];
var b = partitionImageData.data[index + 2];
var a = partitionImageData.data[index + 3];
pixel.data[0] = (selectedColorRGB[0] * (imageData.data[index]+50)) / 255;
pixel.data[1] = (selectedColorRGB[1] * (imageData.data[index + 1]+50)) / 255;
pixel.data[2] = (selectedColorRGB[2] * (imageData.data[index + 2]+50)) / 255;
pixel.data[3] = (a * (imageData.data[index + 3])) / 255;
if(isInPart(r, g, b) == 1)
{
paint(x, y);
}
}
}
}
function paint(x, y)
{
context_paintLayer.fillStyle = 'rgba(' + pixel.data[0] + ',' + pixel.data[1] + ',' + pixel.data[2] + ',' + pixel.data[3] + ')';
context_paintLayer.fillRect(x, y, 1, 1);
//context_paintLayer.putImageData(pixel, x, y);
}
function isInPart(r, g, b, targetPart) {
if ((r >= targetRMin && r <= targetRMax) && (g >= targetGMin && g <= targetGMax) && (b >= targetBMin && b <= targetBMax)) {
return 1;
}
else {
return 0;
}
}
答案 0 :(得分:1)
我建议你画画&#39;在你的循环中直接进入一个imageData,然后在最后做一个单独的puImageData 由于您的画布大小没有变化,您可以缓存数组以避免创建/处理的成本 下面的代码应该更快 我不太了解您的要求,例如,如果图像正在发生变化,因此每次调用都需要getImageDataed(:-)),但您会得到这个想法:
function applyPaint() {
var partitionImageData = context_partitionLayer.getImageData(0, 0, width, height);
var partitionData = partitionImageData.data;
var sourceImageData = context_imageLayer.getImageData(0, 0, width, height);
var sourceData = sourceImageData.data;
var destImageData = context_paintLayer.getImageData(0, 0, width, height);
var destData = destImageData.data;
applyPaint = function (selectedColor) {
var selectedColorRGB = selectedColor.split("-");
var index = 0;
var selectedR = selectedColorRGB[0];
var selectedG = selectedColorRGB[1];
var selectedB = selectedColorRGB[2];
// cache arrays for speed up
var _partitionData = partitionData;
var _sourceData = sourceData ;
var _destData = destData;
for (var y = targetStartY; y < targetEndY; y++) {
for (var x = targetStartX; x < targetEndX; x++) {
index = ((width * y) + x) << 2;
var r = _partitionData[index];
var g = _partitionData[index + 1];
var b = _partitionData[index + 2];
if (isInPart(r, g, b) == 1) {
var a = _partitionData[index + 3];
_destData[index] = (selectedR * (_sourceData[index] + 50)) >> 8;
_destData[index + 1] = (selectedG * (_sourceData[index + 1] + 50)) >> 8;
_destData[index + 2] = (selectedB * (_sourceData[index + 2] + 50)) >> 8;
_destData[index + 3] = (a * (_sourceData[index + 3])) >> 8;
}
}
}
context_paintLayer.putImageData(destImageData, 0, 0);
}
return applyPaint.apply(this, arguments);
}
编辑:如果您计划每次更新整个图像,可以将两个for循环简化为:
var pixelCount = width*height;
var index = 0;
while (pixelCount--) {
// process index
// ...
index+=4;
}
编辑2:
对于给定图像,这是一种获得实时重新着色的方法(意味着图像速率> 60 fps)。 我们的想法是通过使用复合模式/混合模式为您计算gpu。
http://dev.w3.org/fxtf/compositing-1/
第1步) 重新处理分区图像以获取分区掩码画布,该画布将包含全白色 适用于符合条件的像素,黑色适用于不匹配的像素。
它将像
一样构建• build new canvas to store the partition mask.
• for each pixel of the partition image :
if (condition on the partition data r,g,b )
partitionMaskImageData[ ...r and g and b and a ] = 255
else
partitionMaskImageData[ ...r and g and b and a ] = 0
现在,为您的操作构建一个静态临时画布 每次你想改变颜色:
1) clear the temp canvas.
2) draw the partition mask on the temp canvas.
3) draw the image on the temp canvas using mode 'destination-in'.
4) add 50 to all rgb : draw a rect of color 'rgb(50,50,50) using mode 'lighter'.
5) fill a rect with your selected color using mode 'multiply'
--> now the temp canvas is ready.
6) draw the original image on destination canvas
7) draw the temp canvas on the destination canvas.
这里没有什么麻烦,并非所有浏览器都支持&#39;乘以&#39;,但正如你在这里看到的那样http://caniuse.com/#feat=canvas-blending。
我仍然认为更新将花费不到1毫秒(在桌面上)。