Comment puis-je arrêter la prémultiplication alpha avec imageData image?

Existe-t-il un moyen d'arrêter la prémultiplication du canal alpha pour les données de toile ou une solution de contournement?

Je veux générer une image (dans ce cas, certaines valeurs de rgba aléatoires) et enregistrer le canevas en tant qu'image.

Au cours de la deuxième étape, je veux comparer l'image originale avec l'image générée à l'aide de l'imageData, mais cela ne fonctionnera pas en raison de la prémultiplication du canal alpha de mes pixels rgba dans l'image générée.

L'exemple

function drawImage(ctx) { var img = ctx.createImageData(canvas.width,canvas.height); for (var i=img.data.length;i-=4;) { img.data[i] = Math.floor(Math.random() * 255); img.data[i+1] = Math.floor(Math.random() * 255); img.data[i+2] = Math.floor(Math.random() * 255); img.data[i+3] = Math.floor(Math.random() * 255); } ctx.putImageData(img, 0, 0); // our image data we just set console.log(img.data); // the image data we just placed onto the canvas console.log(ctx.getImageData(0,0,canvas.width, canvas.height).data); } 

Dans la console, vous trouverez deux sorties console.log. Le premier avant la prémultiplication, et le second après la prémultiplication. Ces deux sorties sont différentes, certaines valeurs étant désactivées par 3 ou plus. Cela ne se produit que s'il y a une transparence partielle (l'alpha étant réglé sur autre chose que 255).

Existe-t-il un moyen d'obtenir la même sortie? Des idées sur ce problème? Des idées pour créer quelque chose comme une solution de rechange pour ce problème?

Merci d'avance!

Bleh, c'est un problème reconnu en ce qui concerne les spécifications de toile. Il note:

En raison de la nature à perte de conversion vers et à partir de valeurs de couleur alpha prémultipliées, les pixels qui viennent d'être configurés à l'aide de putImageData () peuvent être retournés à un équivalent getImageData () en tant que valeurs différentes.

Donc ça:

 var can = document.createElement('canvas'); var ctx = can.getContext('2d'); can.width = 1; can.height = 1; var img = ctx.createImageData(1, 1); img.data[0] = 40; img.data[1] = 90; img.data[2] = 200; var ALPHAVALUE = 5; img.data[3] = ALPHAVALUE; console.log(img.data); ctx.putImageData(img, 0, 0); console.log(ctx.getImageData(0, 0, 1, 1).data); 

les sorties:

 [40, 90, 200, 5] [51, 102, 204, 5] 

Dans tous les navigateurs.

Il s'agit donc d'une opération à perte, il n'y a pas de solution de contournement, sauf si elles modifient les spécifications pour donner une option pour ne pas utiliser la prémultiplication. Cela a été discuté dès 2008 dans la liste de diffusion de WHATWG, et ils ont décidé qu'un «aller-retour» / l'identité des données d'image de mise / obtention n'est pas une promesse que la spécification est prête à exiger.

Si vous devez "sauvegarder" les données d'image, vous ne pouvez pas l'enregistrer et conserver la même fidélité à l'aide de putImageData. Les solutions de contournement en dessinant les données alpha complètes vers un canevas temporaire et en redessinant le canevas principal avec un plus petit globalAlpha ne fonctionneront pas non plus.

Donc, vous avez de la chance. Pardon.


À ce jour (12 mai 2014), cela reste discuté sur la liste WHATWG: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2014-May/296792.html

Eh bien, c'est encore un bummer …

Je suppose que si vous l'utilisez dans une texture pour webgl vous pouvez simplement passer comme un ensemble d'octets uniformes