开发者

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)
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜