移动设备上的糟糕画布GetImageData()/PutImageData()性能 [英] Horrible Canvas GetImageData() / PutImageData() performance on mobile

查看:139
本文介绍了移动设备上的糟糕画布GetImageData()/PutImageData()性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一些HTML5游戏,在将我的精灵加载到地图的开头时,我使用GetImageData()/遍历所有图像/PutImageData()进行了一些处理.

I'm doing a little HTML5 game and, while loading my sprites at the beginning of the map, I do some processing with GetImageData() / looping over all the image / PutImageData().

这在我的PC上非常好用,但是,在我的手机上,它是如此之慢.

This works fantastically great on my PC, however, on my cell phones it's horrendously slow.

PC: 5-6 ms
iPhone 4: 300-600 ms
Android HTC Desire S: 2500-3000 ms

我一直在进行一些非常基础的基准测试,并且GetImageData和PutImageData都运行非常快,而循环浏览内容却花费了很长时间.

I've been doing some VERY basic benchmarking, and both GetImageData and PutImageData run very fast, what's taking long is the looping through the contents.

现在,我很显然希望手机速度变慢,但是1000x听起来有点过分,并且HTC上的加载大约需要4分钟,所以这是行不通的.此外,游戏中的其他所有内容都可以以非常合理的速度运行(主要是因为屏幕小得离谱,但对于手机上的JS而言,它仍然可以正常工作)

Now, I obviously expect a slowdown on the phone, but 1000x sounds a bit excessive, and the loading takes about 4 minutes on my HTC, so that's not going to work. Also, everything else in the game works at very reasonable speed (mainly because the screen is ridiculously smaller, but still, it works surprisingly fine for JS on a cell phone)

我在此处理中所做的基本上是使精灵达到一定程度.我只是遍历所有像素,然后将它们乘以<1.就这些.

What I'm doing in this processing is basically "darkening" the sprite to a certain level. I simply loop through all the pixels, and multiply them by a value < 1. That's all.

由于这太慢了...是否可以使用Canvas功能(合成,不透明度等),而不用一个接一个地循环遍历所有像素,是一种更好的方法来完成相同的事情?

Since this is too slow... Is there a better way of doing the same thing, using the Canvas functionality, (compositing, opacity, whatever), without looping through all the pixels one by one?

注意:此层具有一些100%透明像素和一些100%不透明像素.两者都必须保持100%不透明或100%透明.

NOTE: This layer has some 100% transparent pixels, and some 100% opaque pixels. Both need to remain either 100% opaque or 100% transparent.

我想到的东西不起作用:
1)在不透明性较低的新画布上绘制精灵.这将行不通,因为我需要让精灵保持不透明,只是要变暗.
2)绘制精灵,并在其顶部绘制半透明的黑色矩形.这会使它们变暗,但也会使我的透明像素不再透明...

Things I've thought of that wouldn't work:
1) Painting the sprites in a new canvas, with lower opacity. This won't work because i need the sprites to remain opaque, just darker.
2) Painting the sprites, and painting a semi-transparent black rect on top of them. This will make them darker, but it'll also make my transparent pixels not transparent anymore...

有什么想法吗?

这是我正在使用的代码,以防万一您看到其中非常愚蠢的东西:

This is the code I'm using, just in case you see something terribly idiotic in it:

function DarkenCanvas(baseImage, ratio) {
    var tmpCanvas = document.createElement("canvas");
    tmpCanvas.width = baseImage.width;
    tmpCanvas.height = baseImage.height;
    var ctx = tmpCanvas.getContext("2d");
    ctx.drawImage(baseImage, 0, 0);

    var pixelData = ctx.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height);
    var length = pixelData.data.length;
    for (var i = 0; i < length; i+= 4) {
        pixelData.data[i] = pixelData.data[i] * ratio;
        pixelData.data[i + 1] = pixelData.data[i + 1] * ratio;
        pixelData.data[i + 2] = pixelData.data[i + 2] * ratio;
    }

    ctx.putImageData(pixelData, 0, 0);
    return tmpCanvas
}

编辑:这是我要对图像进行处理的一个示例:
原文: http://www.crystalgears.com/isoengine/sprites-ground.png
变暗: http://www.crystalgears.com/isoengine/sprites-ground_darkened.png

This is an example of what i'm trying to do with the image:
Original: http://www.crystalgears.com/isoengine/sprites-ground.png
Darkened: http://www.crystalgears.com/isoengine/sprites-ground_darkened.png

谢谢!
丹尼尔

推荐答案

Phrogz的想法正确.您真的只想使用源于顶部" globalCompositeOperation在整个对象上绘制半透明(或比率透明)的黑色.

Phrogz has the right idea. You really just want to paint a half-transparent (or ratio-transparent) black over the whole thing with 'source-atop' globalCompositeOperation.

像这样: http://jsfiddle.net/F4cNg/

关于这样的复杂暗化实际上有一个很好的问题,但是作者删除了它,这实在令人遗憾.即使在形状复杂的情况下,也有可能在绘制的东西上制作黑口罩.它们可能无法帮助您,但是为了完整性,以及任何人在寻找暗画布"的东西时,其中某些部分保持明亮(排除区域),可以使用"xor" globalCompositeOperation来完成,如下所示:

There was actually a good question on sophisticated darkening like this but the author deleted it which is a real shame. It's certainly possible to make dark-masks on drawn stuff, even with sophisticated shapes. They may not help you, but for the sake of completeness and for anyone searching for "darken canvas" stuff where some parts are kept light (exclusion zones), that can be done with the 'xor' globalCompositeOperation, like this:

http://jsfiddle.net/k6Xwy/1/

这篇关于移动设备上的糟糕画布GetImageData()/PutImageData()性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆