在Javascript中同步加载Base64编码的图像

时间:2014-08-04 09:10:40

标签: javascript image base64 webgl

我有一组~200 base64编码的PNG(全部来自一个共享的JSON文件),我想直接在循环中加载为WebGL纹理,而不必求助于回调/事件处理程序(用于更简单的代码和更少的事件处理开销)。有没有办法在Javascript中执行此操作?

我知道加载base64编码图像的规范方法是通过数据URI。但似乎设置src对象的Image属性实际上并不解码图像数据,而只是将其排队以进行异步加载(意味着将Image对象作为WebGL纹理上传设置src属性后失败;设置上传纹理的onload处理程序成功。)

1 个答案:

答案 0 :(得分:1)

为什么呢?你为什么要同步这样做?浏览器中的JavaScript不是为了同步运行而设计的。你将冻结浏览器并可能获得“此脚本执行时间太长”对话框。

异步不难做到,为什么不这样做呢?

var loadTextureFromImage = function(url, callback) {
   // use cyan as the default color.
   var initialColor = new Uint8Array([0,255,255,255]);

   // make a texture with 1x1 pixels so we can use the texture immediately
   // while we wait for the image to load
   var tex = gl.createTexture();
   gl.bindTexture(gl.TEXTURE_2D, tex);
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, 
                 gl.RGBA, gl.UNSIGNED_BYTE, initialColor); 

   var img = new Image();
   img.onload = function() {
      gl.bindTexture(gl.TEXTURE_2D, tex);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      callback(img);
   };

   return tex;
};

var loadTexturesFromImages(listOfImages, callback) {
   var numLeftToDownload = listOfImages.length;

   var checkFinished = function() {
     --numLeftToDownload;
     if (numLeftToDownload == 0 && callback) {
       callback();
     }
   };

   return listOfImages.map(function(url) {
     return loadTexturesFromImage(url, checkFinished);
   });
};

以下是使用上述功能的一些代码

var imagesToLoad = [
   "http://foo.com/image1.jpg",
   "http://foo.com/image2.jpg",
   "data:image/png;base64,iVBORw0KG...",
];

var textures = loadTexturesFromImages(imagesToLoad);

现在你可以开始渲染了。它们都将以青色呈现,并在下载/解码时更新到图像。

如果您想等到它们全部下载完毕,请提供回复loadTexturesFromImages

我想你问题的简短答案是,“不,你不能同步解码图像”。答案很长,如果你想同步解码它们you'll have to decode them yourself。但现在你回到上面提到的问题。也就是说,你将冻结浏览器,你的用户可能会收到一个对话框,询问他们是否要杀死该脚本。