我有一个特定的案例,但我一般也很好奇。
我有一个画布,我使用createImageData获取它的ImgData,并且我将它的数据属性设置为其他东西,然后使用PutImageData并将此修改后的ImgData传递给它。
我的PureScript版本失败,尽管在控制台中使用Javascript编写逻辑可以完美无缺地工作。 错误是:
foreign.js:423 Uncaught TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D':
parameter 1 is not of type 'ImageData'.
在PureScript中:
getCleanBuffer :: forall e. Context2D -> Eff (canvas :: Canvas | e) ImageData
getCleanBuffer ctx = do
imgData <- getImageData ctx 0.0 0.0 160.0 144.0
return imgData { data = buffer }
where buffer = asUint8ClampedArray $ A.replicate (160*144*4) 0
在控制台中编写此javascript(arr为160 * 144 * 4零)
var arr2 = new Uint8ClampedArray(arr);
var imgData = ctx.getImageData(0,0,160,144);
imgData.data = arr2;
ctx.putImageData(imgData,0,0);
我调试了getCleanBuffer,这是我发现的内容
var getCleanBuffer = function (ctx) {
var buffer = Data_TypedArray.asUint8ClampedArray(Data_Array.replicate((160 * 144 | 0) * 4 | 0)(0));
return function __do() {
var v = Graphics_Canvas.getImageData(ctx)(0.0)(0.0)(160.0)(144.0)();
var $9 = {};
for (var $10 in v) {
if (v.hasOwnProperty($10)) {
$9[$10] = v[$10];
};
};
$9.data = buffer;
return $9;
这个$ 9(带有修改数据的ImgData副本)变量在检查时显示不是ImgData类型,就像v(原始的ImgData)那样,但它只是一个&#39; Object&#39 ;。 它缺少v的宽度和高度,但即使我在调试期间修复它,我仍然会得到同样的错误。
我认为问题在于新对象是无类型记录。宽度和高度未被复制的事实是另一个问题。
我可以编写一个javascript函数来手动设置数据属性。 但总的来说,这种情况似乎很常见,我肯定错过了一些东西,不是吗?
谢谢!
答案 0 :(得分:3)
在这种情况下,ImageData
的类型不正确,它是记录的类型同义词,但将JavaScript类类型值视为记录是不安全的,原因完全在于您在这里发现。
我已经按照菲尔的建议开了a bug report。
对于一般情况,这是镜头派上用场的地方。您定义了_data :: LensP ImageData Uint8ClampedArray
之类的镜头,然后可以执行imgData # _data %~ buffer
以获得类似于更新语法的内容。
答案 1 :(得分:0)
我根本不知道purescript,所以我不会回答你问题的标题,但对于你的确切情况,这不是你应该如何创建一个&#34; 干净的ImageData &#34;
不同的浏览器具有ImageData
对象的不同实现,并且由于specs仅需要"TypedArray"作为data
属性,因此您无法确定每个UA(related Q/A)中此缓冲区的类型应为Uint8ClampedArray
。 (现在living specs确实将此TypedArray
的类型指定为Uint8ClampedArray
。)
但幸运的是,当canvas API已经有context2D.createImageData(width, height)
方法或 check-supported-browsers {{1}时,您似乎正在尝试重新发明轮子。 }如果您位于worker(ImageData(Uint8ClampedArray)
不可用)
所以只需使用它,它就可以在支持canvas API的任何UA中使用,而且你不必担心复制任何类型。