Попытка оптимизировать алгоритм для процента определенного цвета на холсте - PullRequest
4 голосов
/ 26 февраля 2012

У меня есть следующий маленький кусочек кода, который я использую, чтобы определить процентное содержание цвета на холсте, в этом случае цвет прозрачный, который imageData.data возвращает как [0,0,0,0]

Поскольку я возвращаю этот процент на мышиную мышку, запускать его довольно дорого, пытаясь его оптимизировать. Также имейте в виду, что цвет холста постоянно меняется, поэтому мне нужно каждый раз захватывать imageData и повторять его.

Конечно, узким местом является функция scratchPercentage, мне нужен способ оптимизировать его, например, получать только новые изменения и не проходить через все данные изображений каждый раз.

scratchFunc: function(e, $this, event)
{
    e.pageX = Math.floor(e.pageX - $this.canvas_offset.left);
    e.pageY = Math.floor(e.pageY - $this.canvas_offset.top);

    $this['scratch' + event](e, $this);

    if($this.settings['scratch' + event])
        $this.settings['scratch' + event](e, $this.scratchPercentage($this));
},

scratchPercentage: function($this)
{
    var hits = 0;
    var imageData = $this.ctx.getImageData(0,0,$this.canvas.width,$this.canvas.height)

    for(var i=0, ii=imageData.data.length; i<ii; i=i+4)
    {
        if(
            imageData.data[i] == 0 &&
            imageData.data[i+1] == 0 &&
            imageData.data[i+2] == 0 &&
            imageData.data[i+3] == 0
        ) hits++;
    }

    return hits / ($this.pixels) * 100;
},

Ответы [ 2 ]

2 голосов
/ 26 февраля 2012

Начните с этой модификации:

scratchPercentage: function($this)
{
    var hits = 0;
    var imageData = $this.ctx.getImageData(0,0,$this.canvas.width,$this.canvas.height).data
    var pixels = imageData.length;

    for(var i=0, ii=pixels; i<ii; i=i+4)
    {
        if(
            imageData[i] == 0 &&
            imageData[i+1] == 0 &&
            imageData[i+2] == 0 &&
            imageData[i+3] == 0
        ) hits++;
    }

    return hits / ($this.pixels) * 100;
}

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

Помимо этих двух изменений, я недумаю, что вы можете сделать scratchPercentage() более стройным.Не зная подробностей того, как ваш холст меняется от кадра к кадру, я не могу предложить какие-либо оптимизации только для расчета изменений.В зависимости от ваших требований к точности, вы можете рассмотреть возможность проверки каждого другого пикселя.

Я также могу придумать примерное решение WebGL, но оно не будет простым.В конечном итоге, если вы не располагаете какой-либо достоверной информацией о том, что изменилось между текущим и предыдущим кадрами, вы не сможете заранее рассчитать этот процент или значительно ускорить его.

Изменить: В зависимости от размера вашего холста, вы можете попытаться изменить размер его копии в памяти до 50% и сделать ваши расчеты на этом.Оно не будет идеальным, но оно должно быть относительно точным.

1 голос
/ 27 февраля 2012

1) Уменьшите частоту дискретизации.

Не вызывайте вычисления каждый раз, когда происходит событие mousemove, лучше сохраните mouseX, mouseY и затем вызовите функцию-образец в setInterval (поэкспериментируйте со значением интервала - где 100% -ное и безопасное значение - это интервал рендеринга) петля)

или используйте какую-нибудь функцию газа, как в http://documentcloud.github.com/underscore/#throttle

2) Если эта функция не должна быть сверхточной, пропустите несколько пикселей

скажем, каждый второй for (...; i = i + 8)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...