在JavaScript中复制插件窗口

时间:2014-05-22 02:06:04

标签: firebreath

我有一个FireBreath插件,以10 Hz的频率绘制到800 x 480的窗口。我想在HTML页面上复制此窗口作为缩略图视图(类似于120 x 72)。理想情况下,缩略图也会以10 Hz的频率更新,但1 Hz是可以接受的。

我有一些工作代码,但它太慢而无法使用。

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 Hz帧的地方率(测试在Chrome中完成)。

如何让插件代码更快?还有另一种方法可以达到相同的效果吗?或者这只是插件的限制?

1 个答案:

答案 0 :(得分:0)

从任何类型的NPAPI插件中将二进制数据传输到javascript的唯一半性能方法是对其进行base64编码并将其作为字符串发送。

如果我正在做你正在尝试的事情,我可能会将其编码为jpeg或其他东西并将其发送回img标签作为数据uri使用。

如果您尝试逐个像素地发送它,您的表现将不会接近足够快的速度。