Copy imageData by value in JavaScript
In my application I have a function that processes Canvas ImageData. It looks something like this:
function processData(imagedata, filters) {
var data = imagedata.data;
//manipulate data with filters
imageData.data = data;
return imageData;
}
I have been using it like this:
var imageData = processData(imageData, {...});
But because the imageData object is passed by reference it will also work like this:
processData(imageData, {...}); // no assignment
I've come to a point in my project where I need to be able to process some imageData while still开发者_JAVA技巧 having access to the original data. My first attempt was similar to the following:
var originalData = imageData;
var processedData = processData(imageData, {...});
This of course would result in to identical imageDatas.
So my second thought was to edit the processsData function so it somehow manipulates a copy of the imageData, instead of the passed imageData. All my attempts to do this have failed or have been horribly inefficient. Just wondering if there is a special way to do this. Thanks in advance.
According to the latest specification ImageData
object data
attribute is initialized to a Uint8ClampedArray
object (instead of earlier used CanvasPixelArray
object), so data within ImageData
could be easily copied with set
method:
function copyImageData(ctx, src)
{
var dst = ctx.createImageData(src.width, src.height);
dst.data.set(src.data);
return dst;
}
Just thought I would add one more solution to this thread along with a link to the duplicate thread on which I found the solution. I am re-posting it here because, in my case it offered an advantage.
They propose simply cloning the data of the ImageData object with
var dataCopy = new Uint8ClampedArray(imageData.data);
Later, if you want to restore this data to an ImageObject you use
imageData.data.set(dataCopy);
imageData may be the original instance from which you cloned the data or a new ImageData object.
In my case this method is better because I am working with ImageData objects inside of a WorkerThread. WorekerThreads are not allowed access to the canvas object or its context so as far as I can tell the techniques here would not help me. This solution; however, did the trick. Thanks All.
Duplicate Thread Offering Other Solutions.
I think you should be able to create a copy pretty easily:
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;
}
(The first argument is the graphics context.)
Then you can call "processImageData" with a copy:
var newImage = processImageData(copyImageData(context, imageData));
edit — I'll try a fiddle to see whether ".slice()" works on the "data" array - I think it will but it's always good to make sure.
The ImageData constructor can be used to clone image data.
function cloneImageData(imgData) {
return new ImageData(imgData.data, imgData.width, imgData.height)
}
精彩评论