Скопируйте imageData по значению в JavaScript - PullRequest
11 голосов
/ 13 апреля 2011

В моем приложении есть функция, которая обрабатывает 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. Все мои попытки сделать это потерпели неудачу или были ужасно неэффективны. Просто интересно, есть ли особый способ сделать это. Заранее спасибо.

Ответы [ 3 ]

27 голосов
/ 12 августа 2012

В соответствии с последней спецификацией ImageData объект data атрибут инициализируется в Uint8ClampedArray объект (вместо ранее использованного CanvasPixelArray объект), поэтому данные в ImageData могут быть легко скопированы с помощью метода set:

function copyImageData(ctx, src)
{
    var dst = ctx.createImageData(src.width, src.height);
    dst.data.set(src.data);
    return dst;
}
4 голосов
/ 06 марта 2013

Просто подумал, что добавлю еще одно решение к этой теме вместе со ссылкой на дублирующую тему, по которой я нашел решение. Я публикую его здесь, потому что в моем случае это дало преимущество.

Они предлагают просто клонировать данные объекта ImageData с помощью

var dataCopy = new Uint8ClampedArray(imageData.data);

Позже, если вы хотите восстановить эти данные в объекте ImageObject, который вы используете

imageData.data.set(dataCopy);

imageData может быть исходным экземпляром, из которого вы клонировали данные, или новым объектом ImageData.

В моем случае этот метод лучше, потому что я работаю с объектами ImageData внутри WorkerThread. WorekerThreads не разрешен доступ к объекту canvas или его контексту, так как, насколько я могу судить, методы здесь не помогут. Это решение; однако сделал свое дело. Спасибо всем.

Повторяющаяся тема, предлагающая другие решения.

1 голос
/ 13 апреля 2011

Я думаю, вы сможете создать копию довольно легко:

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;
}

(первый аргумент - это графический контекст.)

Затем вы можете вызвать "processImageData" с помощьюcopy:

var newImage = processImageData(copyImageData(context, imageData));

edit - я попробую скрипку, чтобы увидеть, работает ли ".slice ()" над массивом "data" - думаю, будет, но всегда хорошочтобы убедиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...