Javascript: Rendez PNG stocké sous Uint8Array sur l'élément Canvas sans URI de données

J'essaie de rendre une image PNG stockée dans un javascript Uint8Array . Le code que j'ai essayé à l'origine était le suivant:

 var imgByteStr = String.fromCharCode.apply(null, this.imgBytes); var pageImg = new Image(); pageImg.onload = function(e) { // Draw onto the canvas canvasContext.drawImage(pageImg, 0, 0); }; // Attempt to generate the Data URI from the binary // 3rd-party library adds toBase64() as a string function pageImg.src="data:image/png;base64,"+encodeURIComponent(imgByteStr.toBase64()); 

Cependant, j'ai constaté que, pour une raison quelconque, la fonction onload ne fonctionnait jamais (j'avais des points d'arrêt configurés en chrome et il ne frappait jamais). J'ai trouvé que si je définissais le src dans une URL au lieu de Data URI, cela fonctionnait correctement. Cependant, en raison de certaines contraintes, je ne peux pas me référer directement à l'URL de l'image, c'est-à-dire qu'il doit être chargé depuis UInt8Array .

En outre, pour compliquer les choses un peu plus, ces images peuvent avoir une taille de mégaoctets. D'après ce que j'ai lu, il y a des problèmes de compatibilité avec la tentative d'utilisation d'URI de données pour des images très volumineuses. Pour cette raison, je suis extrêmement hésitant à les utiliser.

La question est donc de savoir comment rendre ce réseau d'octets en tant que PNG sur un contexte de toile sans utiliser d'URI de données ou directement à l'URL de l'image?


J'ai également essayé d'utiliser quelque chose comme le suivant pour manipuler les données d'image directement à l'aide de la fonction putImageData . Gardez à l'esprit que je ne comprend pas à 100% comment fonctionne cette fonction

 var imgdata = canvasContext.createImageData(this.baseHeight, this.baseWidth); var imgdatalen = imgdata.data.length; for(var i=0; i<imgdatalen; i++) { imgdata.data[i] = _this.imgBytes[i]; } canvasContext.putImageData(imgdata, 0, 0); 

Il a été soulevé d'un blog dont j'ai été fermé depuis l'onglet. Je m'excuse donc de l'inspiration pour ne pas donner un crédit approprié.


De plus, tout en martelant lentement sur cette chose, j'ai rencontré une erreur dans Chrome SECURITY_ERR: DOM Exception 18 . Il s'avère que, dès qu'une image est chargée dans un canevas utilisant drawImage, elle ne peut pas être récupérée sans solutions supplémentaires. Une publication du blog Chromium sur le sujet a été particulièrement utile

Si vous avez les données PNG en mémoire (ce que je pense être ce que vous décrivez), vous pouvez en créer une image. En HTML, il ressemblerait à:

  <img src="data:image/png;base64,KSjs9JdldhAlisflAkshf==" /> 

En JavaScript, vous pouvez faire de même:

 var image = document.createElement('img'); image.src = 'data:image/png;base64,' + base64Data; 

Notez que vous pouvez modifier le type MIME si vous ne disposez pas de données PNG.

Vous pouvez ensuite dessiner l' image sur votre canevas en utilisant context.drawImage(image, 0, 0) ou similaire.

La partie restante du puzzle consiste à coder le contenu de votre Uint8Array dans les données Base 64.

 var array = new Uint8Array(), base64Data = btoa(String.fromCharCode.apply(null, array)); 

La fonction btoa n'est pas standard, donc certains navigateurs pourraient ne pas le supporter. Cependant, il semble que la plupart le font . Sinon, vous pourriez trouver un code que j'utilise utile.

Je n'ai testé aucun de cela moi-même!

Si vous avez déjà un UInt8Array, vous devriez envisager d'utiliser Blob et createObjectURL ; createObjectURL attribue une URL spéciale qui permet au navigateur d'accéder à un blob créé en interne de données binaires comme s'il s'agissait d'un fichier chargé en externe.

Lorsqu'il est pris en charge , createObjectURL est une excellente alternative aux énormes URI de données. Vous devrez peut-être revenir à l'utilisation des URI de données dans Opera, IE <10 et toutes les versions les plus récentes de navigateurs mobiles.

 var myArray; //= your data in a UInt8Array var blob = new Blob([myArray], {'type': 'image/png'}); var URL = URL.createObjectURL(blob); //possibly `webkitURL` or another vendor prefix for old browsers.