2014-01-13 2 views
2

Я пытаюсь играть с задержкой веб-камеры на канал в JavaScript, и мой текущий код работает медленно. Вы можете увидеть демо-версию hereЭффективное манипулирование пикселями с использованием javascript Canvas

Мой подход к задержке создает массив из 12 элементов для хранения пикселей (элементы холста), а затем перемещает содержимое из одного кадра в другой путем копирования пикселей (используя вызовы getImageData и putImageData). Поскольку я расщепляющие цветовые каналы, моя функция обновления выглядит следующим образом:

function update() { 
    if (localMediaStream) { 
     // Update history 
     for (var i = hs - 1; i > 0; i--) { 
      var ctxCurr = history[i].getContext('2d'); 
      var ctxPrev = history[i - 1].getContext('2d'); 
      try { 
       ctxCurr.putImageData(ctxPrev.getImageData(0, 0, w, h), 0, 0); 
      } catch (err) { 
       console.log(err); 
      } 
     } 
     // Write the most recent webcam frame 
     var ctx0 = history[0].getContext('2d'); 
     ctx0.drawImage(video, 0, 0, w, h); 
     // Get pixel data for most recent,halfway and last frames in history 
     var r = history[0].getContext('2d').getImageData(0, 0, w, h).data; 
     var g = history[hs/2].getContext('2d').getImageData(0, 0, w, h).data; 
     var b = history[hs - 1].getContext('2d').getImageData(0, 0, w, h).data; 
     // Get a frame and it's pixels 
     var imageData = ctx0.getImageData(0, 0, w, h); 
     var data = imageData.data; 
     // Write the r,g,b channels using the offset frames for green and blue channels 
     for (var i = 0; i < data.length; i += 4) { 
      data[i] = r[i]; 
      data[i + 1] = g[i + 1]; 
      data[i + 2] = b[i + 2]; 
     } 

     rgb.putImageData(imageData, 0, 0); 
    } 
} 

Я предполагаю, что я мог бы пропустить, используя красный канал, так как последний кадр уже имеет эту информацию. Есть ли более быстрый способ манипулировать/записывать данные пикселов (кроме getImageData() и putImageData()) или быстрее подходит к тому, чего я пытаюсь достичь?

ответ

2

Похоже, есть несколько способов ускорить то, что вы пытаетесь сделать. getImageData довольно медленный, и putImageData разочаровывает медленность, поэтому устранение этих вызовов всегда будет служить вам хорошо. Вы правы, чтобы забыть о красном канале. Я бы также избавиться от этой линии:

var r = history[0].getContext('2d').getImageData(0, 0, w, h).data; 

Кроме того, вы должны быть в состоянии нарисовать полотно в соответствующем контексте, так долго, как вы освобождаете контекст. Я считаю, что ваша попытка заявление должно выглядеть следующим образом:

try { 
    ctxCurr.clearRect(0, 0, w, h); 
    ctxCurr.drawImage(history[i-1], 0, 0); 
} 

Удаление всех этих избыточных вызовов на putImageData должно помочь.

+1

Спасибо Зак! drawImage - большой импульс по сравнению с putImageData/getImageData –

+0

Я обновил код, и он работает на приличной скорости даже на моем Android. Еще раз спасибо! –

0

Чтобы скомпоновать его, я думаю, что put и getImageData - это единственные способы сделать это через холст. Там есть библиотека javascript, которую вы могли бы использовать. Возможно, вы можете манипулировать источником. Я пробовал демонстрацию, и она кажется значительно более жидкой, чем ваша (хотя мне нравятся эффекты трипсинга на вашем). Вы можете найти библиотеку here.

+0

«эффект трипсинга цвета» - это то, что делает его медленным, потому что несколько раз в секунду я копирую пиксели для 12 изображений 320x240 (примерно 11059200 пикселей в секунду). Я быстро посмотрел на библиотеку, с которой вы связались, но, похоже, использует флэш-резерв. Мой вопрос заключается в javascript для ручного кода, я думаю. Я уже тестировал с помощью [actionscript] (http://wonderfl.net/c/aGds) –

Смежные вопросы