在我的应用程序中,我有一个处理Canvas ImageData的函数。它看起来像这样:
function processData(imagedata, filters) {
var data = imagedata.data;
//manipulate data with filters
imageData.data = data;
return imageData;
}
我一直在使用它:
var imageData = processData(imageData, {...});
但是因为imageData对象是通过引用传递的,所以它也会像这样工作:
processData(imageData, {...}); // no assignment
我已经在我的项目中找到了一个点,我需要能够处理一些imageData,同时仍然可以访问原始数据。我的第一次尝试类似于以下内容:
var originalData = imageData;
var processedData = processData(imageData, {...});
这当然会导致相同的imageDatas。
所以我的第二个想法是编辑processsData函数,因此它以某种方式操纵了imageData的副本,而不是传递的imageData。我尝试这样做的所有尝试都失败了,或者效率非常低。只是想知道是否有一种特殊的方法来做到这一点。提前谢谢。
答案 0 :(得分:27)
根据latest specification ImageData
对象data
属性初始化为Uint8ClampedArray
对象(而不是之前使用过的CanvasPixelArray
对象),因此{ {1}}可以使用ImageData
方法轻松复制:
set
答案 1 :(得分:4)
我想我会在这个帖子中添加一个解决方案以及一个指向我找到解决方案的重复线程的链接。我在这里重新发布它,因为在我的情况下它提供了一个优势。
他们建议只使用
克隆ImageData对象的数据var dataCopy = new Uint8ClampedArray(imageData.data);
稍后,如果要将此数据还原到ImageObject,请使用
imageData.data.set(dataCopy);
imageData可能是您从中克隆数据的原始实例或新的ImageData对象。
在我的情况下,这种方法更好,因为我正在使用WorkerThread中的ImageData对象。 WorekerThreads不允许访问画布对象或其上下文,所以我可以告诉这里的技术对我没用。这个解决方案然而,做了伎俩。谢谢大家。
答案 2 :(得分:1)
我认为您应该能够轻松创建副本:
function copyImageData(context, original) {
var rv = context.createImageData(original.width, original.height);
// would
// rv.data = Array.prototype.slice.call(original.data, 0);
// work?
for (var i = 0; i < original.data.length; ++i)
rv.data[i] = original.data[i];
return rv;
}
(第一个参数是图形上下文。)
然后你可以调用&#34; processImageData&#34;副本:
var newImage = processImageData(copyImageData(context, imageData));
编辑 - 我会尝试一个小提琴来看看&#34; .slice()&#34;适用于&#34;数据&#34;数组 - 我认为它会,但确保总是好的。