Ужасный холст GetImageData () / PutImageData () на мобильных устройствах

Я играю в небольшую HTML5-игру и, загружая свои спрайты в начале карты, я выполняю некоторую обработку с помощью GetImageData () / зацикливаю все изображение / PutImageData ().

Это фантастически отлично работает на моем ПК, однако на моих мобильных телефонах он ужасающе медленный.

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

Я провел ОЧЕНЬ базовый тест, и GetImageData и PutImageData работают очень быстро, что занимает много времени, так это цикл

Я очевидно ожидаю замедления работы телефона, но 1000x звучит немного чрезмерно, и загрузка занимает примерно 4 минуты на моем HTC, так что это не сработает.Кроме того, все остальное в игре работает с очень разумной скоростью (в основном из-за того, что экран смехотворно меньше, но все же он работает на удивление хорошо для JS на мобильном телефоне)


В этой обработке я в основном "затемняю" "спрайт до определенного уровня. Я просто перебираю все пиксели и умножаю их на значение

Поскольку это слишком медленно ... Есть ли лучший способ сделать то же самое, используя функциональные возможности Canvas (композитинг, непрозрачность и т. Д.), Без перебора всех пикселей один за другим?

ПРИМЕЧАНИЕ: Этот слой имеет около 100% прозрачных пикселей и около 100% непрозрачных пикселей. Оба должны оставаться либо на 100% непрозрачными, либо на 100% прозрачными.

То, о чем я думал, что не сработает:
1) Рисуем спрайты на новом холсте с меньшей непрозрачностью. Это не сработает, потому что мне нужно, чтобы спрайты оставались непрозрачными, только более темными.
2) Раскрашиваем спрайты и рисуем поверх них полупрозрачный черный прямоугольник. Это сделает их темнее, но при этом мои прозрачные пиксели больше не станут прозрачными ...

Есть идеи?

Это код, который я использую, на случай, если вы заметите в нем что-то ужасно идиотское:

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

Спасибо!
Даниэль

8
задан Daniel Magliola 10 December 2011 в 03:42
поделиться