Pourquoi réglage est-il des valeurs CanvasPixelArray de HTML5 ridiculement lent et comment puis-je le faire plus vite?

StackOverflow https://stackoverflow.com/questions/2573212

Question

Je suis en train de faire des effets visuels dynamiques à l'aide la manipulation de pixels de toile HTML 5, mais je suis en cours d'exécution dans un problème où la mise en pixels dans le CanvasPixelArray est ridiculement lent.

Par exemple, si je code comme:

imageData = ctx.getImageData(0, 0, 500, 500);

for (var i = 0; i < imageData.length; i += 4){
    imageData.data[i] = buffer[i];
    imageData.data[i + 1] = buffer[i + 1];
    imageData.data[i + 2] = buffer[i + 2];
}

ctx.putImageData(imageData, 0, 0);

Le profilage avec Chrome révèle, il fonctionne 44% plus lent que le code suivant où CanvasPixelArray n'est pas utilisé.

tempArray = new Array(500 * 500 * 4);
imageData = ctx.getImageData(0, 0, 500, 500);

for (var i = 0; i < imageData.length; i += 4){
    tempArray[i] = buffer[i];
    tempArray[i + 1] = buffer[i + 1];
    tempArray[i + 2] = buffer[i + 2];
}

ctx.putImageData(imageData, 0, 0);

Je pense que la raison de ce ralentissement est dû à la conversion entre le Javascript double et les entiers non signés 8bit internes, utilisé par le CanvasPixelArray.

  1. Est-ce deviné juste?
  2. Y at-il de toute façon de réduire le temps passé dans les valeurs de réglage du CanvasPixelArray?
Était-ce utile?

La solution

Essayez la mise en cache une référence à la matrice de pixels de data. Votre ralentissement pourrait être attribuée à la propriété supplémentaire accède à imageData.data. Voir cet article pour plus d'explications.

par exemple. Cela devrait être plus rapide que ce que vous avez actuellement.

var imageData = ctx.getImageData(0, 0, 500, 500),
    data = imageData.data,
    len = data.length;

for (var i = 0; i < len; i += 4){
 data[i] = buffer[i];
 data[i + 1] = buffer[i + 1];
 data[i + 2] = buffer[i + 2];
}

ctx.putImageData(imageData, 0, 0);

Autres conseils

Je ne sais pas si cela vous aide parce que vous voulez manipuler les pixels, mais pour moi, dans Firefox 3.6.8, juste l'appel à putImageData était très, très lent, sans faire aucune manipulation de pixels. Dans mon cas, je voulais juste restaurer une version précédente de l'image qui avait été enregistré avec getImageData. Trop lent.

Au lieu de cela, je l'ai bien travailler en utilisant à la place toDataUrl / drawImage. Pour moi, il travaille assez vite que je peux l'appeler au sein de gestion d'un événement mousemove:

Pour enregistrer:

savedImage = new Image()  
savedImage.src = canvas.toDataURL("image/png")

à restaurer:

ctx = canvas.getContext('2d')  
ctx.drawImage(savedImage,0,0)

On dirait que vous faites une sorte de « blitting », alors peut-être drawImage ou tout at-once putImageData pourrait aider. Looping un quart de million de fois pour copier les pixels individuellement, plutôt que d'utiliser des opérations massives « blitting », a tendance à être beaucoup plus lent - et pas seulement en Javascript, -.)

Curieusement, les boucles à travers des réseaux d'objets 2D sont plus rapides que un tableau 1D décalage calcs et aucun objet. Format en conséquence et voir si cela aide (dans mes tests, il était 20x plus rapide).

(heads up: ce script pourrait planter votre navigateur Si vous exécutez, asseyez-vous serré pendant quelques minutes et laisser faire sa chose) http://jsfiddle.net/hc52jx04/16/

function arrangeImageData (target) {

var imageCapture = target.context.getImageData(0, 0, target.width, target.height);
var imageData = {
    data: []
};
imageData.data[0] = [];
var x = 0;
var y = 0;
var imageLimit = imageCapture.data.length;

for (var index = 0; index < imageLimit; index += 4) {

    if (x == target.width) {
        y++;
        imageData.data[y] = [];
        x = 0;
    }

    imageData.data[y][x] = {
        red: imageCapture.data[index],
        green: imageCapture.data[index + 1],
        blue: imageCapture.data[index + 2],
        alpha: imageCapture.data[index + 3]
    };
    x++;
}
return imageData;

}


function codifyImageData (target, data) {

var imageData = data.data;

var index = 0;
var codedImage = target.context.createImageData(target.width, target.height);

for (var y = 0; y < target.height; y++) {

    for (var x = 0; x < target.width; x++) {

        codedImage.data[index] = imageData[y][x].red;
        index++;
        codedImage.data[index] = imageData[y][x].green;
        index++;
        codedImage.data[index] = imageData[y][x].blue;
        index++;
        codedImage.data[index] = imageData[y][x].alpha;
        index++;
    }

}

return codedImage;

}

Plus d'informations: http: / /discourse.wicg.io/t/why-a-straight-array-for-canvas-getimagedata/1020/6

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top