2014-05-22 1 views
0

У меня есть плагин FireBreath, который окрашивается в окно 800 x 480 с частотой 10 Гц. Я хотел бы дублировать это окно на HTML-странице в виде миниатюр (что-то вроде 120 х 72). В идеале миниатюра будет обновляться с частотой 10 Гц, хотя 1 Гц будет приемлемой.Дублирование окна плагина в JavaScript

У меня есть рабочий код, но он слишком медленный, чтобы его можно было использовать.

Javascript начинает получать контекст холста и массив манипулировать (вдохновленный https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipulation-with-typed-arrays/):

var canvas = document.getElementById('thumbnail') 
var context = canvas.getContext('2d'); 
var imgData = context.createImageData(120, 72); 
var buf = new ArrayBuffer(imgData.data.length); 
var buf8 = new Uint8ClampedArray(buf); 
var data = new Uint32Array(buf); 

В JavaScript я хотел бы сделать что-то вроде

for (n = 0; n < data.length; ++n) { 
    data[n] = 0xff0000ff; // paint pixel red 
} 

с последующим

imgData.data.set(buf8); 
context.putImageData(imgData, 0, 0); 

который выполняется очень быстро. Проблема в том, что я хочу передать ответственность за рисование миниатюры плагина. Поэтому вместо цикла JavaScript я делаю что-то вроде document.getElementById("plugin").paintThumbnail(data), переходя в Uint32Array data в качестве параметра.

Реализация paintThumbnail в плагин выглядит следующим образом:

void MyPluginAPI::paintThumbnail(const FB::JSObjectPtr& data) { 
    if (!data) 
     throw FB::invalid_arguments(); 
    int size = data->GetProperty("length").convert_cast<int>(); 

    /* method 1 - call "set" per pixel - slowest */ 
    for (int n = 0; n < size; n++) { 
     FB::VariantList pixel = FB::variant_list_of(0xff0000ff); 
     data->Invoke("set", FB::variant_list_of(pixel)(n)); // paint the nth pixel red 
    } 
    /* -- */ 

    /* method 2 - call "SetProperty" per pixel - faster */ 
    for (int n = 0; n < size; n++) { 
     data->SetProperty(n, 0xff0000ff); // paint the nth pixel red 
    } 
    /* -- */ 

    /* method 3 - write to array buffer then call "set" once - fastest */ 
    uint32_t* vals = new uint32_t[size]; 
    for (int n = 0; n < size; n++) { 
     vals[n] = 0xff0000ff; // paint the nth pixel red 
    } 

    std::vector<uint32_t> valVec(vals, vals + size); 
    FB::VariantList vars = FB::make_variant_list(valVec); 
    data->Invoke("set", FB::variant_list_of(vars)); 
    /* -- */ 
} 

(Очевидно, что как только я получаю эту работу я буду рисовать что-то интересное - не только красное.) Каждый из трех указанных выше способов для изменения Данные JSObjectPtr намного медленнее, чем прямой JavaScript, и нет, где почти достигнута частота кадров 10 Гц (тестирование было выполнено в Chrome).

Как я могу сделать код плагина быстрее? Есть ли другой способ добиться того же результата? Или это просто ограничение плагинов?

ответ

0

Единственный полупроцессорный способ передачи двоичных данных в javascript из плагина NPAPI любого типа - это base64 кодировать его и отправлять его как строку.

Если бы я делал то, что вы пытаетесь, я бы, вероятно, кодировал его как jpeg или что-то еще, и отправить его обратно для использования в теге img в качестве uri данных.

Если вы попробуете отправить пиксель за пикселем, производительность будет не так близко к достаточно быстрому.

+0

Спасибо @taxilian, что сделал трюк. – user1972265