我有一个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中完成)。
如何让插件代码更快?还有另一种方法可以达到相同的效果吗?或者这只是插件的限制?
答案 0 :(得分:0)
从任何类型的NPAPI插件中将二进制数据传输到javascript的唯一半性能方法是对其进行base64编码并将其作为字符串发送。
如果我正在做你正在尝试的事情,我可能会将其编码为jpeg或其他东西并将其发送回img标签作为数据uri使用。
如果您尝试逐个像素地发送它,您的表现将不会接近足够快的速度。